package com.egdigital.allzic.service;

import java.lang.Thread.UncaughtExceptionHandler;

import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.LocalBroadcastManager;
import android.text.Html;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.RemoteViews;
import android.widget.TextView;

import com.egdigital.allzic.ApplicationGlobal;
import com.egdigital.allzic.R;
import com.egdigital.allzic.data.object.Station;
import com.egdigital.allzic.service.PlayerRadio.RadioPlayerCallBack;
import com.egdigital.allzic.service.Scheduler.Mode;
import com.egdigital.allzic.service.Scheduler.OnScheduleTimeListener;
import com.egdigital.allzic.ui.activity.ActivityPlayerNew;
import com.google.android.gms.analytics.HitBuilders;
import com.google.android.gms.analytics.Tracker;

public class ServiceStreaming extends ServiceSoundManagement {

	private static final String				TAG					= ServiceStreaming.class.getSimpleName();		// log
	// info
	public static Station					mStation			= null;
	private String[]						mUrlStreaming;
	public String							mUrlMediaAd			= "";
	private String							mStationTitle;
	// radio time out
	private static final int				TIME_OUT_VALUE		= 15000;										// milli
	private static final int				COUNT_BEFORE_START	= 1;
	private int								mCountStart			= 0;
	private Scheduler						mTimeOutScheduler;
	//
	private static boolean					mIsRunning			= false;
	private UncaughtExceptionHandler		mDefaultUEH;
	private static final String				SERVICE_PREFIX		= "com.egdigital.allzic.service.streaming.";
	public static final String				SERVICE_PLAY		= SERVICE_PREFIX + "play";
	public static final String				SERVICE_STOP		= SERVICE_PREFIX + "stopping";
	public static final String				SERVICE_LOADING		= SERVICE_PREFIX + "loading";
	public static final String				SERVICE_PERCENT		= SERVICE_PREFIX + "percent";
	public static final String				SERVICE_METADATA	= SERVICE_PREFIX + "metadata";
	public static final String				SERVICE_ERROR		= SERVICE_PREFIX + "error";
	public static final String				SERVICE_END			= SERVICE_PREFIX + "song";
	public static final String				SERVICE_KILLED		= SERVICE_PREFIX + "killed";
	// notification
	protected NotificationCompat.Builder	mNotificationBuilder;
	private boolean							mIsNotificationOn	= false;
	public static final int					NOTIFICATION_ID		= 1;
	public static final String				NOTIFICATION_CLOSE	= "notification_close";
	private View							mLayoutNotification;
	private ImageView						mBtnClose;
	private ImageView						mImage;
	private TextView						mTitle;
	private TextView						mSub;

	public static interface RestartCallBack {

		public void readyForRestart();
	}

	public ServiceStreaming() {
		super();
	}

	@Override
	public void onCreate() {
		super.onCreate();
		if (mLocalBroadcastManager == null) {
			mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);
		}
		registerReceiver(mBroadcastNotification, new IntentFilter(NOTIFICATION_CLOSE));
		prepareNotificationUI();
		setUEH();
		mIsRunning = true;
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Station station = null;
		boolean shouldPlay = false;
		try {
			Bundle extras = intent.getExtras();
			mUrlMediaAd = extras.getString("pub");
			station = extras.getParcelable("station");
			shouldPlay = extras.getBoolean(ActivityPlayerNew.SHOULD_PLAY);
		} catch (Exception e) {
		}
		if (station != null) {
			// urls in good order
			mUrlStreaming = new String[3];
			mUrlStreaming[0] = mUrlMediaAd;
			mUrlStreaming[1] = station.getmFlux_aac();
			mUrlStreaming[2] = station.getmFlux_mp3();
			// callbacks and init
			if (mPlayerRadio == null) {
				mPlayerRadio = new PlayerRadio();
				setRadioCallbacks();
			}
			// does radio/pub must launch
			if (shouldPlay) {
				startRadio(station);
			} else {
				mStation = station;
			}
		}
		return super.onStartCommand(intent, flags, startId);
	}

	@Override
	public void onDestroy() {
		Log.i(TAG, "finish why ?");
		if (mBroadcastNotification != null) {
			unregisterReceiver(mBroadcastNotification);
		}
		stopStreaming();
		// mPlayerRadio = null;
		hideNotification(true);
		mIsRunning = false;
		super.onDestroy();
	}

	public static boolean isRunning() {
		return mIsRunning;
	}

	/**
	 * notification management
	 */
	private void prepareNotificationUI() {
		LayoutInflater inflater = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		mLayoutNotification = inflater.inflate(R.layout.view_notification, null);
		mBtnClose = (ImageView) mLayoutNotification.findViewById(R.id.notif_close);
		mSub = (TextView) mLayoutNotification.findViewById(R.id.notif_text);
		mTitle = (TextView) mLayoutNotification.findViewById(R.id.notif_title);
		mImage = (ImageView) mLayoutNotification.findViewById(R.id.notif_image);
	}

	private void setupNotification() {
		Context context = getApplicationContext();
		// layout
		RemoteViews contentView = new RemoteViews(context.getPackageName(), R.layout.view_notification);
		if (isPlayingRadio()) {
			contentView.setImageViewResource(R.id.notif_btn_play, R.drawable.stop_small);
		} else {
			contentView.setImageViewResource(R.id.notif_btn_play, R.drawable.play_small);
		}
		contentView.setImageViewResource(R.id.notif_image, R.drawable.icon);
		contentView.setTextViewText(R.id.notif_title, Html.fromHtml(mStation.getmTitle()));
		contentView.setTextViewText(R.id.notif_text, Html.fromHtml(mStation.getmSubtitle()));
		// intent
		final Intent notificationIntent = new Intent(context, ActivityPlayerNew.class).setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP).putExtra(ActivityPlayerNew.STATION, (Parcelable) mStation);
		PendingIntent contentIntent = PendingIntent.getActivity(context, NOTIFICATION_ID, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
		// pending
		final PendingIntent closeIntent = PendingIntent.getBroadcast(context, 0, new Intent(NOTIFICATION_CLOSE), PendingIntent.FLAG_UPDATE_CURRENT);
		// builder
		mNotificationBuilder = new NotificationCompat.Builder(context);
		mNotificationBuilder.setSmallIcon(R.drawable.icon);
		mNotificationBuilder.setOnlyAlertOnce(true);
		mNotificationBuilder.setContent(contentView);
		mNotificationBuilder.setOngoing(true);
		mNotificationBuilder.setTicker(Html.fromHtml(mStation.getmTitle()));
		mNotificationBuilder.setContentIntent(contentIntent);
		contentView.setOnClickPendingIntent(R.id.notif_close, closeIntent);
		startForeground(NOTIFICATION_ID, mNotificationBuilder.build());
		mIsNotificationOn = true;
	}

	private void hideNotification(boolean removeNotification) {
		if (mIsNotificationOn == true) {
			stopForeground(true);
			mIsNotificationOn = false;
		}
	}

	final BroadcastReceiver	mBroadcastNotification	= new BroadcastReceiver() {

														@Override
														public void onReceive(Context context, Intent intent) {
															String actionString = intent.getAction();
															if (actionString.equalsIgnoreCase(NOTIFICATION_CLOSE)) {
																// stopStreaming();
																stopSelf();
																sendMessageToUI(SERVICE_KILLED);
																hideNotification(true);
															}
														}
													};

	/**
	 * Radio
	 * 
	 * @param station
	 */
	public synchronized void startRadio(Station station) {
		if (mPlayerRadio == null || station == null) {
			sendMessageToUI(SERVICE_STOP);
			return;
		}
		// if (mPlayerRadio.getState() == StreamingState.STOPPING || mPlayerRadio.getState() == StreamingState.PREPARING) {
		// sendMessageToUI(SERVICE_STOP);
		// return;
		// }
		mStation = station;
		String url = "";
		if (station.getmFlux_aac() != null && !station.getmFlux_aac().isEmpty()) {
			url = station.getmFlux_aac();
		} else if (station.getmFlux_mp3() != null && !station.getmFlux_mp3().isEmpty()) {
			url = station.getmFlux_mp3();
		} else {
			sendMessageToUI(SERVICE_ERROR);
			return;
		}
		try {
			mPlayerRadio.start(url);
		} catch (Exception e) {
			sendMessageToUI(SERVICE_ERROR);
		}
		// analytics stations stats
		analyticsSendEvent(station.getmTitle());
		// create and start the timer for time out in case of bad connexions or no error callback
		mTimeOutScheduler = new Scheduler(TIME_OUT_VALUE, 1, Mode.ASC);
		mTimeOutScheduler.setOnScheduleTimeListener(new OnScheduleTimeListener() {

			@Override
			public void onScheduleTime(int count) {
				if (!isPlayingRadio() && mCountStart == COUNT_BEFORE_START) {
					sendMessageToUI(SERVICE_ERROR);
					stopSelf(); // service stop for future restart
					mTimeOutScheduler.stopTimer();
				}
				mCountStart++;
			}
		});
		mTimeOutScheduler.startTimer();
	}

	/**
	 * stop playing and notify ui with a broadcast
	 */
	public synchronized void stopStreaming() {
		if (mPlayerRadio != null) {
			try {
				mPlayerRadio.stop();
				if (mTimeOutScheduler != null) {
					mTimeOutScheduler.stopTimer();
				}
			} catch (Exception e) {
				sendMessageToUI(SERVICE_ERROR);
			}
			if (mPlayerRadio.getState() == StreamingState.PREPARING || mPlayerRadio.getState() == StreamingState.STOPPING) {
				sendMessageToUI(SERVICE_STOP);
				return;
			}
		}
		mPlayerRadio = null;
		// sendMessageToUI(SERVICE_STOP);
	}

	/**
	 * callbacks radio
	 */
	public void setRadioCallbacks() {
		mPlayerRadio.setCallbacks(new RadioPlayerCallBack() {

			@Override
			public void radioPlayerException(Throwable e) {
				sendMessageToUI(SERVICE_ERROR);
			}

			@Override
			public void radioPlayerStarted() {
				setupNotification();
				sendMessageToUI(SERVICE_PLAY);
			}

			@Override
			public void radioPlayerStopped(int perf) {
				sendMessageToUI(SERVICE_STOP);
			}

			@Override
			public void radioPlayerMetadata(String key, String value) {
				// sendMessageToUI(SERVICE_METADATA, key, value);
			}

			@Override
			public void radioPlayerPCMFeedBuffer(boolean isPlaying, int audioBufferSizeMs, int audioBufferCapacityMs) {
				// sendMessageToUI(SERVICE_PERCENT, (int) (audioBufferSizeMs * 100 / audioBufferCapacityMs) + "");
			}
		});
	}

	public static boolean isPlayingRadio() {
		if (mPlayerRadio == null) {
			return false;
		}
		if (mPlayerRadio.isStarted() || mPlayerRadio.isPrepared()) {
			return true;
		}
		return false;
	}

	public static boolean isloadingRadio() {
		if (mPlayerRadio == null) {
			return false;
		}
		if (mPlayerRadio.isPreparing()) {
			return true;
		}
		return false;
	}

	/**
	 * listen to app crash and stop the service in case
	 */
	private Thread.UncaughtExceptionHandler	unCaughtExceptionHandler	= new Thread.UncaughtExceptionHandler() {

																			@Override
																			public void uncaughtException(Thread thread, Throwable ex) {
																				hideNotification(true);
																				stopStreaming();
																				mDefaultUEH.uncaughtException(thread, ex);
																			}
																		};

	private void setUEH() {
		mDefaultUEH = Thread.getDefaultUncaughtExceptionHandler();
		Thread.setDefaultUncaughtExceptionHandler(unCaughtExceptionHandler);
	}

	/**
	 * Send an event to GoogleAnalytics server
	 * 
	 * @param context
	 *        the application context
	 * @param action
	 * @param category
	 * @param label
	 * @param value
	 */
	public void analyticsSendEvent(String name) {
		// Get tracker.
		Tracker tracker = ((ApplicationGlobal) ApplicationGlobal.getContext()).getTracker();
		// Set value name.
		tracker.send(new HitBuilders.EventBuilder().setCategory("traffic").setAction("radio").setLabel(name).setValue(1).build());
	}
}
